/*
EvoGen, Evolutionary Geneura is a framework for simulating distributed evolutionary computation experiments
Copyright (C) 2008 Junta de Andalucia CICE project P06-TIC-02025

This file is part of EvoGen.

EvoGen is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.

EvoGen is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with EvoGen; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

contact:  http://geneura.ugr.es, https://forja.rediris.es/svn/geneura/evogen
*/
package mirabilis.org.simplices;

import mirabilis.org.config.Configuration;



public class Vertex implements Comparable<Vertex>,Cloneable{
	protected Coordinates _coordinates;
	
	protected double fitness = Double.MIN_VALUE;
		
	public Vertex(Coordinates coordinates) {
		setCoordinates(coordinates);
	}
	
	
	public Coordinates getCoordinates() {
		return _coordinates;
	}
	
	public double[] getVertexAsDouble() throws FitnessNotEvaluatedException{
		if(fitness != Double.MIN_VALUE){
			// A vertex is the array of coordinates (x,y,...) plus the evaluation f(x,y,...)
			double[] vertex = new double[_coordinates.getDimensions()+1]; 
			System.arraycopy(_coordinates.getCoordinatesAsDouble(), 0, vertex, 0, _coordinates.getDimensions());
			vertex[_coordinates.getDimensions()] = fitness;
			return vertex;
		}else
			throw new FitnessNotEvaluatedException("Fitness of coordinate must be evaluated");
	}
	
	public void setCoordinates(Coordinates coordinates) {
		this._coordinates = coordinates;
	}

	public double getFitness() throws FitnessNotEvaluatedException{
		if(fitness != Double.MIN_VALUE)
			return fitness;
		else
			throw new FitnessNotEvaluatedException("Fitness of coordinate must be evaluated");		
	}

	public void setFitness(double fitness) {
		this.fitness = fitness;
	}
		
	public Object clone() {
		Vertex theclone = new Vertex((Coordinates)this._coordinates.clone());
		theclone.fitness = this.fitness;
		return theclone;
	}
	
	public boolean better(Vertex vertex) {
		return (Configuration.minimization) ? vertex.fitness > this.fitness: vertex.fitness < this.fitness;
	}
	
	
	public boolean worst(Vertex vertex) {
		return (Configuration.minimization) ? vertex.fitness < this.fitness: vertex.fitness > this.fitness;
	}
			
	public boolean value_reached(double value){
		return (Configuration.minimization) ? this.fitness <= value:  this.fitness >= value;
	}
	
	public String asStringOfTorus(){
		return _coordinates.asStringOfTorus()+" "+fitness;
	}
	
	public String asString(){
		return _coordinates.asString()+" "+fitness;
	}
	
	public boolean equals(Object obj) {
	if (obj instanceof Vertex) {
		Vertex ind = (Vertex) obj;
		if(ind.fitness == this.fitness){
			//System.out.println(ind.fitness+" "+this.fitness);
			if (!ind._coordinates.equals(this._coordinates)) return false;
		}else return false;
	}else return false;
	return true;
	}
	
	//Distinguishes two vertices' fitness with a maximal accuraccy of 1e-16
	public int compareTo(Vertex o) {
		double accuracy = 1e18;
		if (Configuration.minimization){
			return (int)((this.fitness - o.fitness)*accuracy);
		}else
			return (int)((o.fitness - this.fitness)*accuracy);
		
	}
	
	

	
}

class FitnessNotEvaluatedException extends Exception {
	
	/**
	 * 
	 */
	private static final long serialVersionUID = 3376680309517227262L;
	private String message = null;

	public FitnessNotEvaluatedException(){
		super();
	}
	
	public FitnessNotEvaluatedException(String message) {
        super(message);
        this.message = message;
    }
 
    public FitnessNotEvaluatedException(Throwable cause) {
        super(cause);
    }
 
    @Override
    public String toString() {
        return message;
    }
 
    @Override
    public String getMessage() {
        return message;
    }

}
